﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;

namespace SerialPortLib
{
    
    public class RS232:ISerialPort
    {
       
        private SerialPort _Port = null;
        private Code _Code = null;
        public RS232Params Params { get; set; }

        public RS232() {    }
        public RS232(RS232Params Params):this()
        {
            this.Params = Params;
            this._Code = new Code(Params.EndFlag);
        }

        #region ISerialPort 成员

        public int Open()
        {
            //实例化
            if (_Port == null)
            {
                _Port = new SerialPort(Params.PortName, Params.BaudRateValue, Params.ParityValue, Params.DataBitsValue, Params.StopBitsValue);
                _Port.DataReceived+=new SerialDataReceivedEventHandler(Drp);
            }
            //如果未打开
            try
            {
                if (!_Port.IsOpen)
                    _Port.Open();
            }
            catch (Exception)
            {
                return -1;
            }
            return 0;
        }

        public int Send(string data)
        {
            if (data == null) return -1;    //发送数据为NULL时，返回 -1

            ValidatePortOpen();
            data = _Code.Encode(data);
            _Port.Write(data);  //写入数据
            return data.Length;
        }
        
        public string Receive()
        {
            ValidatePortOpen();
            return RcvData();
        }

        public int Close()
        {
            int _r = 0;
            if (_Port == null)
            {
                _r = 0;
            }
            else if (_Port.IsOpen)
            {
                _r = 2;
                _Port.Dispose();    //释放资源
                _Port.Close();
            }
            else
            {
                _r = 1;
                _Port.Close();
            }
            return _r;
        }

        #endregion

        //当接收到数据时回调的方法
        private void Drp(object sender, SerialDataReceivedEventArgs e)
        {

            string _data = _Code.Decode(RcvData());
            if (ReceivedHandler != null)
            {
                DataReceivedEventArgs re = new DataReceivedEventArgs(_data);
                ReceivedHandler(this, re);
            }
        }

        private bool ValidatePortOpen()
        {
            bool _r = true;
            if (_Port == null || !_Port.IsOpen)
            {
                //初始化并打开串口，如果未设置
                int _open = Open();
                if (_open != 0)
                {
                    _r = false;
                    throw new Exception("The serial port " + Params.PortName + " isn't opened!");
                }
            }
            return _r;
        }

        private string RcvData()
        {
            StringBuilder _rcv = new StringBuilder(this._Port.ReadExisting());
            while (!string.IsNullOrEmpty(_rcv.ToString()) && !_Code.IsCompleted(_rcv.ToString()))
            {
                //接收的数据不是NULL & Empty，并且未结束
                _rcv.Append(this._Port.ReadExisting());
            }
            return _rcv.ToString();
        }

        /// <summary>
        /// 公共静态方法，获得当前设备所有可使用的串口名称数组
        /// </summary>
        /// <returns></returns>
        public static string[] AllEnablePortNames()
        {
            return SerialPort.GetPortNames();
        }


        #region ISerialPort 成员


        public event DataReceivedHandler ReceivedHandler;

        #endregion
    }

    
}
